package com.openwater.network;

import java.io.File;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;

import android.util.Log;

/**
 * 
 * @author fuxp
 * @version 1.0
 */
public class DownloadThread extends Thread {

    private static final String TAG = DownloadThread.class.getName();

    private final URL mUrl;
    private final File mSaveFile;

    private int mFromSize = 0;
    private int mToSize = 0;
    private int mThreadId = 0;
    private int retryTimes = 0;
    private int mFromSize2 = 0;
    private FileDownloader mDownloader = null;
    private OnProcessListener mProcessListener = null;

    interface OnProcessListener {
        void onProcess(int threadId, int offset, int length);

        void onFail(int threadId, int length);
    }

    void setOnProcessListener(OnProcessListener l) {
        mProcessListener = l;
    }

    DownloadThread(FileDownloader downloader, URL downUrl, File saveFile, int fromSize, int toSize,
            int threadId) {
        mUrl = downUrl;
        mSaveFile = saveFile;
        mThreadId = threadId;
        mToSize = toSize;
        mFromSize = fromSize;
        mFromSize2 = mFromSize;
        mDownloader = downloader;
        setName(downUrl + " : " + threadId);
    }

    @Override
    public void run() {
        // if download task not finish
        boolean finish = false;
        int length = 0;
        String requestMothed = "POST";
        a: while (retryTimes < FileDownloader.RETRY_TIMES && !finish) {
            if (mFromSize < mToSize && !finish) {
                try {
                    HttpURLConnection http = (HttpURLConnection) mUrl.openConnection();
                    http.setConnectTimeout(5 * 1000);
                    http.setRequestMethod(requestMothed);
                    http.setRequestProperty("Accept",
                            "image/gif, image/jpeg, image/pjpeg, image/pjpeg, "
                                    + "application/x-shockwave-flash, application/xaml+xml, "
                                    + "application/vnd.ms-xpsdocument, application/x-ms-xbap, "
                                    + "application/x-ms-application, application/vnd.ms-excel, "
                                    + "application/vnd.ms-powerpoint, application/msword, */*");
                    http.setRequestProperty("Accept-Language", "zh-CN");
                    http.setRequestProperty("Referer", mUrl.toString());
                    http.setRequestProperty("Charset", "UTF-8");

                    // set download range
                    http.setRequestProperty("Range", "bytes=" + mFromSize + "-" + mToSize);
                    Log.d(TAG, "range mThreadId: " + mThreadId + " mFromSize: " + mFromSize
                            + " mToSize:" + mToSize);
                    http.setRequestProperty(
                            "User-Agent",
                            "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0;"
                                    + ".NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; "
                                    + ".NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)");
                    http.setRequestProperty("Connection", "Keep-Alive");

                    final InputStream inStream = http.getInputStream();
                    final RandomAccessFile accessfile = new RandomAccessFile(mSaveFile, "rwd");
                    accessfile.seek(mFromSize);
                    final byte[] buffer = new byte[1024];
                    int offset = 0;
                    length = 0;
                    try {
                        while ((offset = inStream.read(buffer, 0, 1024)) != -1) {
                            accessfile.write(buffer, 0, offset);
                            mFromSize += offset;
                            length += offset;
                            if (mProcessListener != null) {
                                Log.d(TAG, "notify mThreadId: " + mThreadId + " offset: " + offset
                                        + " length:" + length);
                                mProcessListener.onProcess(mThreadId, offset, length);
                            }
                            if (mDownloader.isPause() || mDownloader.isStop()) {
                                DDBHelper.updateMultithreadsDownloadInfor(mUrl.toString(),
                                        mThreadId, length);
                                Log.d(TAG, "download fail:" + mDownloader.isPause());
                                mFromSize = mFromSize2;
                                break a;
                            }
                        }
                    } finally {
                        accessfile.close();
                        inStream.close();
                    }
                    Log.d(TAG, "Thread :" + mThreadId + " download finish " + length);
                    finish = true;
                    break a;
                } catch (Exception e) {
                    length = 0;
                    retryTimes++;
                    finish = false;
                    mFromSize = mFromSize2;
                    requestMothed = retryTimes % 2 == 0 ? "POST" : "GET";
                    e.printStackTrace();
                    Log.d(TAG, "Exception is happened ,mThreadId: " + mThreadId + " retry times:"
                            + retryTimes);
                }
            }
        }
        if (!finish && mProcessListener != null) {
            mProcessListener.onFail(mThreadId, length);
        }
    }

    /**
     * @return true if this thread download finished
     */
    boolean isFinish() {
        return mFromSize == mToSize;
    }
}
